import { launch } from "puppeteer";
import { randomUA } from "./ua.js";
import {
  readFile,
  writeFile,
  searchPathToCode,
  codeToSearchPath,
  sleep,
} from "./utils.js";

const KR_PATH = "hifini/keyword-rules.json";

class Hifini {
  config = {
    headless: "new",
    // headless: false,
    baseUrl: "https://www.hifini.com",
    searchPath: "/search.htm",
    keywordsSelector: "input.form-control",
    submitSelector: "button[type=submit]#submit",
    searchListSelector: ".card-body ul.list-unstyled .media-body .subject a",
    searchPaginationListSelector: "ul.pagination li.page-item a",
  };

  async search(keyword, pageNum = 1) {
    const {
      headless,
      baseUrl,
      searchPath,
      keywordsSelector,
      submitSelector,
      searchListSelector,
      searchPaginationListSelector,
    } = this.config;

    let res;

    const getPagination = async (page) => {
      const pagination = await page.$$eval(
        searchPaginationListSelector,
        (item) =>
          item.map((e) => ({
            page: e.innerText,
            href: e.href,
          }))
      );
      pagination.pop();
      return {
        info: pagination,
        totalPages:
          pagination.length === 0
            ? 1
            : parseInt(pagination.at(-1).page.slice(3)),
      };
    };

    const getList = async (page) => {
      const pagintaionInfo = await getPagination(page);
      const currentPageTableRows = await page.$$eval(
        searchListSelector,
        (item) =>
          item.map((e) => ({
            title: e.innerText,
            href: e.href,
          }))
      );
      return {
        totalPages: pagintaionInfo.totalPages,
        data: currentPageTableRows,
      };
    };
    const browser = await launch({ headless });
    const page = await browser.newPage();
    await page.setUserAgent(randomUA());
    await page.setViewport({
      width: 1024,
      height: 768,
      deviceScaleFactor: 1,
    });
    const fsContent = (await readFile(KR_PATH).catch(() => "{}")) || "{}";
    const rules = JSON.parse(fsContent);
    if (rules[keyword]) {
      const path = `${baseUrl}${codeToSearchPath(rules[keyword], pageNum)}`;
      await page.goto(path);
      await sleep(500);
      const data = await getList(page);
      res = Object.assign(data, { pageNum });
    } else {
      const searchUrl = `${baseUrl}${searchPath}`;
      await page.goto(searchUrl);
      await sleep(500);
      await page.type(keywordsSelector, keyword);
      await page.click(submitSelector);
      await sleep(500);
      const encodePath = await page.$eval("body", () => location.pathname);
      rules[keyword] = searchPathToCode(encodePath);
      await writeFile(KR_PATH, JSON.stringify(rules, null, 2));
      if (pageNum > 1) {
        const path = `${baseUrl}${codeToSearchPath(rules[keyword], pageNum)}`;
        await page.goto(path);
        await sleep(500);
      }
      const data = await getList(page);
      res = Object.assign(data, { pageNum });
    }
    await browser.close();
    return res;
  }

  async getSong(url) {
    const { baseUrl, headless } = this.config;
    const browser = await launch({ headless });
    const page = await browser.newPage();
    await page.setUserAgent(randomUA());
    await page.setViewport({
      width: 1024,
      height: 768,
      deviceScaleFactor: 1,
    });
    await page.goto(url, { waitUntil: "load", timeout: 0 });
    await sleep(1200);
    const info = await page.$eval("body", () => window?.ap4?.music);
    const lrc = await page.$$eval("h5", (h5s) => {
      const t = h5s.filter((e) => e.innerText.includes("歌词")).at(0);
      const lyrics = [];
      let current = t?.nextElementSibling;
      while (current?.localName === "p") {
        lyrics.push(current.innerText);
        current = current?.nextElementSibling;
      }
      return lyrics;
    });
    info.lrc = lrc;

    /**
     *  author: "周杰伦"
     *  pic: "https://y.gtimg.cn/music/photo_new/T002R300x300M0000024bjiL2aocxT.jpg"
     *  title: "珊瑚海"
     *  url: "get_music.php?key=M7MEHrKFYW2ylaJP+6dfAGZbuYFlj6aLQrpjNDOCE0Vhdd8PkAccXkCB6AUx5vTPyZ2x5sYq9QfGqMXHRis"
     * */
    info.url = `${baseUrl}/${info.url}`;
    await browser.close();
    return info;
  }
}

export const hi = new Hifini();

// const data = await hi.search("周杰伦");
// console.log(data);

// const data2 = await hi.search("周杰伦", 2);
// console.log(data2);

// const song = await hi.getSong("https://www.hifini.com/thread-13568.htm");
// console.log(JSON.stringify(song, null, 2));
